/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.osiris.persistence.controllers.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;


import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityNotFoundException;
import javax.persistence.Persistence;
import javax.persistence.Query;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.osiris.persistence.Asignacionesproyecto;
import org.osiris.persistence.Proyecto;
import org.osiris.persistence.Requisito;
import org.osiris.persistence.Requisitosdeproyecto;
import org.osiris.persistence.Usuario;
import org.osiris.persistence.controllers.ProyectoInterface;
import org.osiris.persistence.controllers.exceptions.IllegalOrphanException;
import org.osiris.persistence.controllers.exceptions.NonexistentEntityException;
import org.osiris.persistence.controllers.exceptions.PreexistingEntityException;

/**
 *
 * @author amartinez
 */
public class ProyectoJpaController implements ProyectoInterface {

	Logger logger=Logger.getLogger(this.getClass());
	
    public ProyectoJpaController() {
    	emf = CreadorPU.getEntityManagerFactory();
    }
    private EntityManagerFactory emf = null;

    /* (non-Javadoc)
	 * @see org.osiris.persistence.controllers.ProyectoInterface#getEntityManager()
	 */
    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }
    
    /* (non-Javadoc)
	 * @see org.osiris.persistence.controllers.ProyectoInterface#create(org.osiris.persistence.Proyecto)
	 */
    public void create(Proyecto proyecto) throws PreexistingEntityException, Exception {
        if (proyecto.getRequisitosdeproyectoList() == null) {
            proyecto.setRequisitosdeproyectoList(new ArrayList<Requisitosdeproyecto>());
        }
        if (proyecto.getAsignacionesproyectoList() == null) {
            proyecto.setAsignacionesproyectoList(new ArrayList<Asignacionesproyecto>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Usuario usuarioidUsuario = proyecto.getUsuarioidUsuario();
            if (usuarioidUsuario != null) {
                usuarioidUsuario = em.getReference(usuarioidUsuario.getClass(), usuarioidUsuario.getIdUsuario());
                proyecto.setUsuarioidUsuario(usuarioidUsuario);
            }
            List<Requisitosdeproyecto> attachedRequisitosdeproyectoList = new ArrayList<Requisitosdeproyecto>();
            for (Requisitosdeproyecto requisitosdeproyectoListRequisitosdeproyectoToAttach : proyecto.getRequisitosdeproyectoList()) {
                requisitosdeproyectoListRequisitosdeproyectoToAttach = em.getReference(requisitosdeproyectoListRequisitosdeproyectoToAttach.getClass(), requisitosdeproyectoListRequisitosdeproyectoToAttach.getRequisitosdeproyectoPK());
                attachedRequisitosdeproyectoList.add(requisitosdeproyectoListRequisitosdeproyectoToAttach);
            }
            proyecto.setRequisitosdeproyectoList(attachedRequisitosdeproyectoList);
            List<Asignacionesproyecto> attachedAsignacionesproyectoList = new ArrayList<Asignacionesproyecto>();
            for (Asignacionesproyecto asignacionesproyectoListAsignacionesproyectoToAttach : proyecto.getAsignacionesproyectoList()) {
                asignacionesproyectoListAsignacionesproyectoToAttach = em.getReference(asignacionesproyectoListAsignacionesproyectoToAttach.getClass(), asignacionesproyectoListAsignacionesproyectoToAttach.getAsignacionesproyectoPK());
                attachedAsignacionesproyectoList.add(asignacionesproyectoListAsignacionesproyectoToAttach);
            }
            proyecto.setAsignacionesproyectoList(attachedAsignacionesproyectoList);
            em.persist(proyecto);
            if (usuarioidUsuario != null) {
                usuarioidUsuario.getProyectoList().add(proyecto);
                usuarioidUsuario = em.merge(usuarioidUsuario);
            }
            for (Requisitosdeproyecto requisitosdeproyectoListRequisitosdeproyecto : proyecto.getRequisitosdeproyectoList()) {
                Proyecto oldProyectoOfRequisitosdeproyectoListRequisitosdeproyecto = requisitosdeproyectoListRequisitosdeproyecto.getProyecto();
                requisitosdeproyectoListRequisitosdeproyecto.setProyecto(proyecto);
                requisitosdeproyectoListRequisitosdeproyecto = em.merge(requisitosdeproyectoListRequisitosdeproyecto);
                if (oldProyectoOfRequisitosdeproyectoListRequisitosdeproyecto != null) {
                    oldProyectoOfRequisitosdeproyectoListRequisitosdeproyecto.getRequisitosdeproyectoList().remove(requisitosdeproyectoListRequisitosdeproyecto);
                    oldProyectoOfRequisitosdeproyectoListRequisitosdeproyecto = em.merge(oldProyectoOfRequisitosdeproyectoListRequisitosdeproyecto);
                }
            }
            for (Asignacionesproyecto asignacionesproyectoListAsignacionesproyecto : proyecto.getAsignacionesproyectoList()) {
                Proyecto oldProyectoOfAsignacionesproyectoListAsignacionesproyecto = asignacionesproyectoListAsignacionesproyecto.getProyecto();
                asignacionesproyectoListAsignacionesproyecto.setProyecto(proyecto);
                asignacionesproyectoListAsignacionesproyecto = em.merge(asignacionesproyectoListAsignacionesproyecto);
                if (oldProyectoOfAsignacionesproyectoListAsignacionesproyecto != null) {
                    oldProyectoOfAsignacionesproyectoListAsignacionesproyecto.getAsignacionesproyectoList().remove(asignacionesproyectoListAsignacionesproyecto);
                    oldProyectoOfAsignacionesproyectoListAsignacionesproyecto = em.merge(oldProyectoOfAsignacionesproyectoListAsignacionesproyecto);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
        	ex.printStackTrace();
            if (findProyecto(proyecto.getIdProyecto()) != null) {
                throw new PreexistingEntityException("Proyecto " + proyecto + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    /* (non-Javadoc)
	 * @see org.osiris.persistence.controllers.ProyectoInterface#edit(org.osiris.persistence.Proyecto)
	 */
    public void edit(Proyecto proyecto) throws IllegalOrphanException, NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Proyecto persistentProyecto = em.find(Proyecto.class, proyecto.getIdProyecto());
            Usuario usuarioidUsuarioOld = persistentProyecto.getUsuarioidUsuario();
            Usuario usuarioidUsuarioNew = proyecto.getUsuarioidUsuario();
            List<Requisitosdeproyecto> requisitosdeproyectoListOld = persistentProyecto.getRequisitosdeproyectoList();
            List<Requisitosdeproyecto> requisitosdeproyectoListNew = proyecto.getRequisitosdeproyectoList();
            List<Asignacionesproyecto> asignacionesproyectoListOld = persistentProyecto.getAsignacionesproyectoList();
            List<Asignacionesproyecto> asignacionesproyectoListNew = proyecto.getAsignacionesproyectoList();
            List<String> illegalOrphanMessages = null;
            for (Requisitosdeproyecto requisitosdeproyectoListOldRequisitosdeproyecto : requisitosdeproyectoListOld) {
                if (!requisitosdeproyectoListNew.contains(requisitosdeproyectoListOldRequisitosdeproyecto)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Requisitosdeproyecto " + requisitosdeproyectoListOldRequisitosdeproyecto + " since its proyecto field is not nullable.");
                }
            }
            for (Asignacionesproyecto asignacionesproyectoListOldAsignacionesproyecto : asignacionesproyectoListOld) {
                if (!asignacionesproyectoListNew.contains(asignacionesproyectoListOldAsignacionesproyecto)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Asignacionesproyecto " + asignacionesproyectoListOldAsignacionesproyecto + " since its proyecto field is not nullable.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            if (usuarioidUsuarioNew != null) {
                usuarioidUsuarioNew = em.getReference(usuarioidUsuarioNew.getClass(), usuarioidUsuarioNew.getIdUsuario());
                proyecto.setUsuarioidUsuario(usuarioidUsuarioNew);
            }
            List<Requisitosdeproyecto> attachedRequisitosdeproyectoListNew = new ArrayList<Requisitosdeproyecto>();
            for (Requisitosdeproyecto requisitosdeproyectoListNewRequisitosdeproyectoToAttach : requisitosdeproyectoListNew) {
                requisitosdeproyectoListNewRequisitosdeproyectoToAttach = em.getReference(requisitosdeproyectoListNewRequisitosdeproyectoToAttach.getClass(), requisitosdeproyectoListNewRequisitosdeproyectoToAttach.getRequisitosdeproyectoPK());
                attachedRequisitosdeproyectoListNew.add(requisitosdeproyectoListNewRequisitosdeproyectoToAttach);
            }
            requisitosdeproyectoListNew = attachedRequisitosdeproyectoListNew;
            proyecto.setRequisitosdeproyectoList(requisitosdeproyectoListNew);
            List<Asignacionesproyecto> attachedAsignacionesproyectoListNew = new ArrayList<Asignacionesproyecto>();
            for (Asignacionesproyecto asignacionesproyectoListNewAsignacionesproyectoToAttach : asignacionesproyectoListNew) {
                asignacionesproyectoListNewAsignacionesproyectoToAttach = em.getReference(asignacionesproyectoListNewAsignacionesproyectoToAttach.getClass(), asignacionesproyectoListNewAsignacionesproyectoToAttach.getAsignacionesproyectoPK());
                attachedAsignacionesproyectoListNew.add(asignacionesproyectoListNewAsignacionesproyectoToAttach);
            }
            asignacionesproyectoListNew = attachedAsignacionesproyectoListNew;
            proyecto.setAsignacionesproyectoList(asignacionesproyectoListNew);
            proyecto = em.merge(proyecto);
            if (usuarioidUsuarioOld != null && !usuarioidUsuarioOld.equals(usuarioidUsuarioNew)) {
                usuarioidUsuarioOld.getProyectoList().remove(proyecto);
                usuarioidUsuarioOld = em.merge(usuarioidUsuarioOld);
            }
            if (usuarioidUsuarioNew != null && !usuarioidUsuarioNew.equals(usuarioidUsuarioOld)) {
                usuarioidUsuarioNew.getProyectoList().add(proyecto);
                usuarioidUsuarioNew = em.merge(usuarioidUsuarioNew);
            }
            for (Requisitosdeproyecto requisitosdeproyectoListNewRequisitosdeproyecto : requisitosdeproyectoListNew) {
                if (!requisitosdeproyectoListOld.contains(requisitosdeproyectoListNewRequisitosdeproyecto)) {
                    Proyecto oldProyectoOfRequisitosdeproyectoListNewRequisitosdeproyecto = requisitosdeproyectoListNewRequisitosdeproyecto.getProyecto();
                    requisitosdeproyectoListNewRequisitosdeproyecto.setProyecto(proyecto);
                    requisitosdeproyectoListNewRequisitosdeproyecto = em.merge(requisitosdeproyectoListNewRequisitosdeproyecto);
                    if (oldProyectoOfRequisitosdeproyectoListNewRequisitosdeproyecto != null && !oldProyectoOfRequisitosdeproyectoListNewRequisitosdeproyecto.equals(proyecto)) {
                        oldProyectoOfRequisitosdeproyectoListNewRequisitosdeproyecto.getRequisitosdeproyectoList().remove(requisitosdeproyectoListNewRequisitosdeproyecto);
                        oldProyectoOfRequisitosdeproyectoListNewRequisitosdeproyecto = em.merge(oldProyectoOfRequisitosdeproyectoListNewRequisitosdeproyecto);
                    }
                }
            }
            for (Asignacionesproyecto asignacionesproyectoListNewAsignacionesproyecto : asignacionesproyectoListNew) {
                if (!asignacionesproyectoListOld.contains(asignacionesproyectoListNewAsignacionesproyecto)) {
                    Proyecto oldProyectoOfAsignacionesproyectoListNewAsignacionesproyecto = asignacionesproyectoListNewAsignacionesproyecto.getProyecto();
                    asignacionesproyectoListNewAsignacionesproyecto.setProyecto(proyecto);
                    asignacionesproyectoListNewAsignacionesproyecto = em.merge(asignacionesproyectoListNewAsignacionesproyecto);
                    if (oldProyectoOfAsignacionesproyectoListNewAsignacionesproyecto != null && !oldProyectoOfAsignacionesproyectoListNewAsignacionesproyecto.equals(proyecto)) {
                        oldProyectoOfAsignacionesproyectoListNewAsignacionesproyecto.getAsignacionesproyectoList().remove(asignacionesproyectoListNewAsignacionesproyecto);
                        oldProyectoOfAsignacionesproyectoListNewAsignacionesproyecto = em.merge(oldProyectoOfAsignacionesproyectoListNewAsignacionesproyecto);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Long id = proyecto.getIdProyecto();
                if (findProyecto(id) == null) {
                    throw new NonexistentEntityException("The proyecto with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    /* (non-Javadoc)
	 * @see org.osiris.persistence.controllers.ProyectoInterface#destroy(java.lang.Long)
	 */
    public void destroy(Long id) throws IllegalOrphanException, NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Proyecto proyecto;
            try {
                proyecto = em.getReference(Proyecto.class, id);
                proyecto.getIdProyecto();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The proyecto with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            List<Requisitosdeproyecto> requisitosdeproyectoListOrphanCheck = proyecto.getRequisitosdeproyectoList();
            for (Requisitosdeproyecto requisitosdeproyectoListOrphanCheckRequisitosdeproyecto : requisitosdeproyectoListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Proyecto (" + proyecto + ") cannot be destroyed since the Requisitosdeproyecto " + requisitosdeproyectoListOrphanCheckRequisitosdeproyecto + " in its requisitosdeproyectoList field has a non-nullable proyecto field.");
            }
            List<Asignacionesproyecto> asignacionesproyectoListOrphanCheck = proyecto.getAsignacionesproyectoList();
            for (Asignacionesproyecto asignacionesproyectoListOrphanCheckAsignacionesproyecto : asignacionesproyectoListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Proyecto (" + proyecto + ") cannot be destroyed since the Asignacionesproyecto " + asignacionesproyectoListOrphanCheckAsignacionesproyecto + " in its asignacionesproyectoList field has a non-nullable proyecto field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            Usuario usuarioidUsuario = proyecto.getUsuarioidUsuario();
            if (usuarioidUsuario != null) {
                usuarioidUsuario.getProyectoList().remove(proyecto);
                usuarioidUsuario = em.merge(usuarioidUsuario);
            }
            em.remove(proyecto);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    /* (non-Javadoc)
	 * @see org.osiris.persistence.controllers.ProyectoInterface#findProyectoEntities()
	 */
    public List<Proyecto> findProyectoEntities() {
        return findProyectoEntities(true, -1, -1);
    }

    /* (non-Javadoc)
	 * @see org.osiris.persistence.controllers.ProyectoInterface#findProyectoEntities(int, int)
	 */
    public List<Proyecto> findProyectoEntities(int maxResults, int firstResult) {
        return findProyectoEntities(false, maxResults, firstResult);
    }

    @SuppressWarnings("unchecked")
	private List<Proyecto> findProyectoEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createQuery("select object(o) from Proyecto as o");
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    /* (non-Javadoc)
	 * @see org.osiris.persistence.controllers.ProyectoInterface#findProyecto(java.lang.Long)
	 */
    public Proyecto findProyecto(Long id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Proyecto.class, id);
        } finally {
            em.close();
        }
    }

    /* (non-Javadoc)
	 * @see org.osiris.persistence.controllers.ProyectoInterface#getProyectoCount()
	 */
    public int getProyectoCount() {
        EntityManager em = getEntityManager();
        try {
            return ((Long) em.createQuery("select count(o) from Proyecto as o").getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    public List<Proyecto> buscarProyectos(String cliente, 
			String descripcion, 
			String estado,
			Date fechaalta,
			Long idProyecto,
			String nombre,
			String referencia,
			String usuario){
		logger.info("Buscando proyectos para nombre:"+nombre+ " descripcion:"+descripcion+" estado "+estado+" referencia "+referencia +"usuario "+usuario+"idProyecto  "+idProyecto +"fechaalta "+fechaalta);
		org.hibernate.Session session = (Session)getEntityManager().getDelegate(); 
    	session.beginTransaction();
    	Criteria criteria = session.createCriteria(Proyecto.class);
		
		if(descripcion!=null){
			
			criteria.add(Restrictions.like("descripcion", "%"+descripcion+"%"));
		}
		if(cliente!=null){			
			criteria.add(Restrictions.like("cliente", "%"+cliente+"%"));
		}
		if(estado!=null){
			criteria.add(Restrictions.eq("estado", estado));
		}
		if(fechaalta!=null){
			criteria.add(Restrictions.ge("fechaalta", fechaalta));			
		}
		if(idProyecto!=null){
			
			criteria.add(Restrictions.eq("idProyecto", idProyecto));
		}
		if(referencia!=null){
			criteria.add(Restrictions.like("referencia", "%"+referencia+"%"));
		}if(nombre!=null){
			criteria.add(Restrictions.like("nombre", "%"+nombre+"%"));
		}if(usuario!=null){
			criteria.add(Restrictions.eq("usuarioidUsuario", usuario));
		}
		logger.info("Query:"+criteria);
		List <Proyecto> proyectos = criteria.list();
        session.getTransaction().commit();        
		logger.info("Resultado:"+proyectos.size()+" proyectos");
		return proyectos;
	}

}
